/*---------------------------------------------------
 *
 * parse_node.h
 *  definitions for parse tree nodes
 * Many of the node types used in parsetrees including
 * a "location" field.This is a byte(not a character) 
 * offset in the original source text, to be used for 
 * positioning an error cousor when there is an error
 * related to the mode. Access to the original source
 * text is needed to make use of the location. 
 *----------------------------------------------------
 */
#ifndef PARSE_NODE_H
#define PARSE_NODE_H

#include "c.h"
#include "nodes/value.h"
#include "nodes/op_list.h"
#include "nodes/primnodes.h"

/* Sort ordering options for ORDER BY */
/* _line_38 */
typedef enum SortByDir
{
  SORTBY_DEFAULT,
  SORTBY_ASC,
  SORTBY_DESC,
  SORTBY_USING,
} SortByDir;

/* _line_46 */
typedef enum SortByNulls
{
	SORTBY_NULLS_DEFAULT,
	SORTBY_NULLS_FIRST,
	SORTBY_NULLS_LAST
} SortByNulls;

/*--------------------------------------------------------
 * Query - 
 *  Parse analysis turns all statement into an Query 
 *  tree(via transformStmt) for further processing by
 *  the rewriter and planner.
 *  Utility statement(i.e. non-optimizable statements)
 *  have the utilityStmt field set, and the Query itself
 *  is mostly dummy.
 *  Planning converts a Query tree into a Plan tree headed
 *  by a PlannedStmt node --- the Query structure is not
 *  used by the executor.
 *--------------------------------------------------------
 */
/* _line_98 */
typedef struct Query
{
  NodeTag type;

  CmdType commandType;  /* select|insert|delete|update|utility */

  bool canSetTag;  /* do I set the command result tag? */

  Node *utilityStmt;  /* non-null if this is a non-optimizabe statement */

  int resultRelation;  /* rtable index of target relation 
			* for INSERT/UPDATE/DELETE; 0 for SELECT */
  bool hasAggs;  /* has aggregates in tlist or havingQual */

  bool hasSubLinks;  /* has subquery SubLink */

  bool hasDistinctOn;  /* dinstinctClause is from DISTINCT ON */

  List *rtable;  /* target list (of TargetEntry) */

  List *returningList;  /* return-values list (of TargetEntry) */

  List *groupClause;  /* a list of SortGroupClause's */

  Node *havingQual;  /* qualifications applied to groups */

  List *distinctClause;  /* a list of SortGroupClause's */

  List *sortClause;  /* a list of SortGroupClause's */
} Query;

/***********************************************************
 * Supporting data structures for Parse Trees
 *
 * Most of these node types appear in raw parsetrees output
 * by the grammar, and get transformed to something else by 
 * the analyzer. A few of them are used as-is in transformed
 * querytrees.
 ***********************************************************/
/*
 * TypeName - specifies a type in definitions
 */
/* _line_172 */
typedef struct TypeName
{
  NodeTag type;
  List *name;  /* qualified name(list of Value strings) */
  unsigned int typeid;
  bool pct_type;  /* %TYPE specified */
  int location;  /* token location, or -1 if unknown */
}TypeName;

/* ColumnRef - specifies a reference to a column
 * 
 * The "fields" list must be nonempty. It can contain string 
 * Value nodes(representing names) and A_Star nodes (representing
 * occurrence of a '*'). Currently, A_Star must appear only as the 
 * last element --- the grammar is responsible for enforcing this!
 */
/* _line_198 */
typedef struct ColumnRef
{
  NodeTag type;
  List *fields;  /* fields names (Value strings) or A_Star */
  int location;  /* token location, or -1 if unknown */
}ColumnRef;

/* A_Expr - infix, prefix, and postfix expressions */
/* _line_218 */
typedef enum A_Expr_Kind
{
  AEXPR_OP,  /* normal operator */
  AEXPR_AND,  /* booleans - name field is unused */
  AEXPR_OR,
  AEXPR_NOT
} A_Expr_Kind;

/* _line_232 */
typedef struct A_Expr
{
  NodeTag type;
  A_Expr_Kind kind;  /* see above */
  List *name;  /* possible-qualified name of operator */
  Node *lexpr;  /* left argument, or NULL if none */
  Node *rexpr;  /* right argument, or NULL if none */
  int location;  /* token location, or -1 if unknown */
}A_Expr;

/* A_Const - a literal constant */
/* _line_245 */
typedef struct A_Const
{
  NodeTag type;
  struct Value val;  /* value(includes type info, see value.h) */
  int location;  /* token location, or -1 if unknown */
}A_Const;

/* A_Star - '*' representing all columns of a table
 * 
 * This can appear within ColumnRef.fields and 
 * ResTarget.indirection lists.
 */
/* _line_290 */
typedef struct A_Star
{
  NodeTag type;
}A_Star;

/*
 * A_Indirection - select a field and/or array element from an expression
 *
 * The indirection list can contain A_Indices nodes (representing
 * subscripting), string Value nodes (representing field selection --- the
 * string value is the name of the field to select), and A_Star nodes
 * (representing selection of all fields of a composite type).
 * For example, a complex selection operation like
 *				(foo).field1[42][7].field2
 * would be represented with a single A_Indirection node having a 4-element
 * indirection list.
 *
 * Currently, A_Star must appear only as the last list element --- the grammar
 * is responsible for enforcing this!
 */
/* _line_320 */
typedef struct A_Indirection
{
  NodeTag type;
  Node *arg;  /* the thing being selected from */
  List *indirection;  /* subscripts and/or field names and/or * */
}A_Indirection;

/*
 * ResTarget -
 *	  result target (used in target list of pre-transformed parse trees)
 *
 * In a SELECT target list, 'name' is the column label from an
 * 'AS ColumnLabel' clause, or NULL if there was none, and 'val' is the
 * value expression itself.  The 'indirection' field is not used.
 *
 * INSERT uses ResTarget in its target-column-names list.  Here, 'name' is
 * the name of the destination column, 'indirection' stores any subscripts
 * attached to the destination, and 'val' is not used.
 *
 * In an UPDATE target list, 'name' is the name of the destination column,
 * 'indirection' stores any subscripts attached to the destination, and
 * 'val' is the expression to assign.
 *
 * See A_Indirection for more info about what can appear in 'indirection'.
 */
 /* _line_355 */
typedef struct ResTarget
{
  NodeTag type;
  char *name;  /* column name or NULL */
  List *indirection;  /* subscripts, field names, and '*', or NIL */
  Node *val;  /* the value expression to compute or assign */
  int location;  /* token location, or -1 if unknown */
}ResTarget;

/*
 * SortBy - for ORDER BY clause
 */
/* _line_367 */
typedef struct SortBy
{
  NodeTag type;
  Node *node;  /* expression to sort on */
  SortByDir sortby_dir;  /* ASC|DESC|USING|default */
  SortByNulls sortby_nulls;	/* NULLS FIRST/LAST */
  List *useOp;  /* name of op to use, if SORTBY_USING */
  int location;  /* operator location, or -1 if none/unknown */
}SortBy;

/*
 * RangeSubselect - subquery appearing in a FROM clause
 */
/* _line_422 */
typedef struct RangeSubselect
{
  NodeTag type;
  Node *subquery;  /* the untransformed sub-select clause */
  Alias *alias;
} RangeSubselect;

/* _line_766 */
typedef struct SortGroupClause
{
  NodeTag type;
  Index tleSortGroupRef;  /* reference into targetlist */
  unsigned int eqop;  /* the equality operator('=' op) */
  unsigned int sortop;  /* the ordering operator('<' op), or 0 */
  bool nulls_first;  /* do NULLS come before normal values? */
}SortGroupClause;

/*----------------------
 * Insert Statement
 *----------------------
 */
/* _line_873 */
typedef struct InsertStmt
{
  NodeTag type;
  RangeVar *relation;  /*relation to insert into */
  List *cols;  /* optional: names of the target columns */
  Node *selectStmt;  /* the source SELECT, or NULL */
  List *returningList; /* list of expressions of return */
}InsertStmt;

/*----------------------
 * Delete Statement
 *----------------------
 */
/* _line_886 */
typedef struct DeleteStmt
{
  NodeTag type;
  RangeVar *relation;  /* relation to delete from */
  List *usingClause;  /* optional using clause for more tables */
  Node *whereClause;  /* qualifications */
  List *returningList;  /* list of expressions to return */
}DeleteStmt;   

/* 
 * SortGroupClause - 
 *   representation of ORDER BY, GROUP BY, DISTINCT, 
 *   DISTINCT ON items
 *
 * You might think that ORDER BY is only interested in defining ordering,
 * and GROUP/DISTINCT are only interested in defining equality. However,
 * one way to implement grouping is to sort and then apply a "uniq"-like
 * filter. So it's also interesting to keep track of possible sort operators
 * for GROUP/DISTINCT, and in particular to try to sort for the grouping
 * in a way that will also yield a requested ORDER BY ordering. So we need
 * to be able to compare ORDER BY and GROUP/DISTINCT lists, which motivates
 * the dicision to give them the same representation.
 *
 * tleSortGroupRef must match ressortgroupref of exactly one entry of the
 *   query's targetlist; that is the expression to be sorted or grouped by.
 * eqop is the OID of the equality operator.
 * sortop is the OID of the ordering operator(a "<" or ">" operator),
 *   or InvalidOid if not available.
 * nulls_first means about what you'd expect. If sortop is InvalidOid
 *   then nulls_first is meaningless and should be set to false.
 *
 * In an ORDER BY item, all fields must be valid. (The eqop isn't essential
 * here, but it's cheap to get it along with the sortop, and requring it to 
 * be valid eases comparisons to grouping items.)
 *
 * In a grouping item, eqop must be valid. If the eqop is a btree equality
 * operator, then sortop should be set to a compatible ordering operator.
 * We prefer to set eqop/sortby/nulls_first to match any ORDER BY item that
 * the query presents for the same tlist item. If there is none, we just use
 * the default ordering op for the datatype.
 *
 * If the tlist item's type has a hash opclass but no btree opclass, then we
 * will set eqop to the hash equality operator, sortop to InvalidOid, and 
 * nulls_first to false. A grouping item of this kind can only be implemented
 * by hashing, and of course it'll never match an ORDER BY item.
 *
 * A query might have both ORDER BY and DISTINCT (or DISTINCT ON) clauses.
 * In SELECT DISTINCT, the dinstinctClause list is as long or longer than the 
 * sortClause list, while in SELECT DISTINCT ON it's typically shorter.
 * The two lists must match up to the end of the short one ---  the parser
 * rearranges the distinctClause if neccesary to make this true.(This
 * restriction ensures that only one sort step is needed to both satisfy the
 * ORDER BY and set up for the Unique step. This is semantically necessary for
 * DISTINCT ON, and presents no real drawback for DISTINCT.)
 */

/*----------------------
 * Update Statement
 *----------------------
 */
/* _line_899 */
typedef struct UpdateStmt
{
  NodeTag  type;
  RangeVar *relation;  /* relation to update */
  List *targetList;  /* the target list(of ResTarget) */
  Node *whereClause;  /* qualifications */
  List *fromClause;  /* optional from clause for more tables */
  List *returningList; /* list of expression to return */
}UpdateStmt;



/*----------------------
 * Select Statement
 *----------------------
 */
/* _line_930 */
typedef struct SelectStmt
{
  NodeTag type;
  
  /* These fields are used only in "leaf" SelectStmts */
  List *distinctClause;  /* NULL, list of DISTINCT IN exprs, or
			   * lcons(NIL,NIL) for all(SELECT DISTINCT)*/
  List *targetList;  /* the target list(of ResTarget) */
  List *fromClause;  /* the FROM cause */
  Node *whereClause;  /* WHERE qualification */
  List *groupClause;  /* GROUP BY clauses */
  Node *havingClause;  /* HAVING conditional-expression */
  
  /* You can add some field when you need more components.
   * But you should check your gram.y for synchronizing.
   */
  List *sortClause;		/* sort clause (a list of SortBy's) */
}SelectStmt;
#endif
